from threading import Thread, Event, Condition, Semaphore
import time


# def countdown(n, started_evt):
#     print('counting starting')
#     time.sleep(10)
#     started_evt.set()   # started_evt线程启动
#     while n > 0:
#         print('T-minus', n)
#         n -= 1
#         time.sleep(2)
#
# start_evt = Event()
# print('Launching countdown')
# t = Thread(target=countdown,args = (10,start_evt))
# t.start()
# start_evt.wait()  # 主线程等待执行到set()
# print('countdown is running')

class PeriodicTimer:
    def __init__(self, interval):
        self._interval = interval
        self._flag = 0
        self._cv = Condition()

    def start(self):
        t = Thread(target=self.run)
        t.daemon = True
        t.start()

    def run(self):
        '''
        Run the timer and notify waiting threads after each interval
        '''
        while True:
            time.sleep(self._interval)
            with self._cv:
                self._flag ^= 1
                self._cv.notify_all()

    def wait_for_tick(self):
        '''
        Wait for the next tick of the timer
        '''
        with self._cv:
            last_flag = self._flag
            while last_flag == self._flag:
                self._cv.wait()  # 等待启动


ptimer = PeriodicTimer(2)  # 实例化对象
ptimer.start()  # 启动该线程


def countdown(nticks):
    while nticks > 0:
        ptimer.wait_for_tick()
        print('T-minus', nticks)
        nticks -= 1


def countup(last):
    n = 0
    while n < last:
        ptimer.wait_for_tick()
        print('Counting', n)
        n += 1


Thread(target=countdown, args=(10,)).start()
Thread(target=countup, args=(5,)).start()


def worker(n, sema):
    sema.acquire()
    print('Working', n)


sema = Semaphore(0)
nworks = 10
for n in range(nworks):
    t = Thread(target=worker, args=(n, sema,))
    t.start()
